/* Start Header **************************************************************/
/*!
\file Matrix3x3.cpp
\author David Seah Seng Chong, sengchong.seah, 250004910
\par sengchong.seah\@digipen.edu)
\date July 07, 2011)
\brief
Copyright (C) 2011 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents
without the prior written consent of DigiPen Institute of
Technology is prohibited.
*/
/* End Header ****************************************************************/


#include "Matrix3x3.h"


#include <string>

#define PIOVER180	0.0174532925199432f

D3DXMATRIX Convert3x3(Matrix3x3 transform)
{
	return D3DXMATRIX(transform.m00, transform.m10, 0, 0,
						transform.m01, transform.m11,0 , 0,
						0, 0, 1, 0,
						transform.m02, transform.m12, 0, 1
						);
}

/**************************************************************************/
/*!
	Assign array values to the matrix elements
	*/
/**************************************************************************/
Matrix3x3::Matrix3x3(const float *pArr)
{
	// Row 1
	m00 = pArr[0];
	m01 = pArr[1];
	m02 = pArr[2];
	// Row 2
	m10 = pArr[3];
	m11 = pArr[4];
	m12 = pArr[5];
	// Row 3
	m20 = pArr[6];
	m21 = pArr[7];
	m22 = pArr[8];
}

/**************************************************************************/
/*!
	Assign the parameters to the matrix elements
	*/
/**************************************************************************/
Matrix3x3::Matrix3x3(float _00, float _01, float _02,
						float _10, float _11, float _12,
						float _20, float _21, float _22)
{
		// Row 1
	m00 = _00;
	m01 = _01;
	m02 = _02;
	// Row 2
	m10 = _10;
	m11 = _11;
	m12 = _12;
	// Row 3
	m20 = _20;
	m21 = _21;
	m22 = _22;
}

/**************************************************************************/
/*!
	Concatenating two matrices and storing the result in the object itself
	*/
/**************************************************************************/
Matrix3x3& Matrix3x3::operator *= (const Matrix3x3 &rhs)
{
		// Row 1
	m00 = ( m00 * rhs.m00 ) + ( m01 * rhs.m10 ) + ( m02 * rhs.m20 );
	m01 = (m00 * rhs.m01  ) + ( m01 * rhs.m11 ) + ( m02 * rhs.m21 );
	m02 = (m00 * rhs.m02  ) + ( m01 * rhs.m12 ) + ( m02 * rhs.m22 );
	// Row 2
	m10 = ( m10 * rhs.m00 ) + ( m11 * rhs.m10 ) + ( m12 * rhs.m20 );
	m11 = ( m10 * rhs.m01 ) + ( m11 * rhs.m11 ) + ( m12 * rhs.m21 );
	m12 = ( m10 * rhs.m02 ) + ( m11 * rhs.m12 ) + ( m12 * rhs.m22 );
	// Row 3
	m20 = ( m20 * rhs.m00 ) + ( m21 * rhs.m10 ) + ( m22 * rhs.m20 );
	m21 = ( m20 * rhs.m01 ) + ( m21 * rhs.m11 ) + ( m22 * rhs.m21 ); 
	m22 = ( m20 * rhs.m02 ) + ( m21 * rhs.m12 ) + ( m22 * rhs.m22 );
	return *this;
		
}

/**************************************************************************/
/*!
	Concatenating two matrices and returning a new matrix
	*/
/**************************************************************************/
Matrix3x3 operator * (const Matrix3x3 &lhs, const Matrix3x3 &rhs)
{
	return Matrix3x3
	(
		( lhs.m00 * rhs.m00 ) + ( lhs.m01 * rhs.m10 ) + ( lhs.m02 * rhs.m20 ),
		( lhs.m00 * rhs.m01 ) + ( lhs.m01 * rhs.m11 ) + ( lhs.m02 * rhs.m21 ),
		( lhs.m00 * rhs.m02 ) + ( lhs.m01 * rhs.m12 ) + ( lhs.m02 * rhs.m22 ),
		( lhs.m10 * rhs.m00 ) + ( lhs.m11 * rhs.m10 ) + ( lhs.m12 * rhs.m20 ),
		( lhs.m10 * rhs.m01 ) + ( lhs.m11 * rhs.m11 ) + ( lhs.m12 * rhs.m21 ),
		( lhs.m10 * rhs.m02 ) + ( lhs.m11 * rhs.m12 ) + ( lhs.m12 * rhs.m22 ),
		( lhs.m20 * rhs.m00 ) + ( lhs.m21 * rhs.m10 ) + ( lhs.m22 * rhs.m20 ),
		( lhs.m20 * rhs.m01 ) + ( lhs.m21 * rhs.m11 ) + ( lhs.m22 * rhs.m21 ),
		( lhs.m20 * rhs.m02 ) + ( lhs.m21 * rhs.m12 ) + ( lhs.m22 * rhs.m22 )
	);
}

/**************************************************************************/
/*!
	This function multiplies the matrix pMtx with the vector rhs 
	and returns the result as a vector
	*/
/**************************************************************************/
Vector2D operator * (const Matrix3x3 &lhs, const Vector2D &rhs)
{
	return Vector2D
	(
		( lhs.m00 * rhs.x ) + ( lhs.m01 * rhs.y ) + ( lhs.m02 * 1.0f ),
		( lhs.m10 * rhs.x ) + ( lhs.m11 * rhs.y ) + ( lhs.m12 * 1.0f )
	);
}

/**************************************************************************/
/*!
	This function sets the matrix pResult to the identity matrix
	*/
/**************************************************************************/
void Mtx33Identity(Matrix3x3 &pResult)
{
	// Row 1
	pResult.m00 = 1;
	pResult.m01 = 0;
	pResult.m02 = 0;
	// Row 2
	pResult.m10 = 0;
	pResult.m11 = 1;
	pResult.m12 = 0;
	// Row 3
	pResult.m20 = 0;
	pResult.m21 = 0;
	pResult.m22 = 1;
}

/**************************************************************************/
/*!
	This function creates a translation matrix from x & y 
	and saves it in pResult
	*/
/**************************************************************************/
void Mtx33Translate(Matrix3x3 &pResult, float x, float y)
{
	// Row 1
	pResult.m00 = 1;
	pResult.m01 = 0;
	pResult.m02 = x;
	// Row 2
	pResult.m10 = 0;
	pResult.m11 = 1;
	pResult.m12 = y;
	// Row 3
	pResult.m20 = 0;
	pResult.m21 = 0;
	pResult.m22 = 1;
}

/**************************************************************************/
/*!
	This function creates a scaling matrix from x & y 
	and saves it in pResult
	*/
/**************************************************************************/
void Mtx33Scale(Matrix3x3 &pResult, float x, float y)
{
	// Row 1
	pResult.m00 = x;
	pResult.m01 = 0;
	pResult.m02 = 0;
	// Row 2
	pResult.m10 = 0;
	pResult.m11 = y;
	pResult.m12 = 0;
	// Row 3
	pResult.m20 = 0;
	pResult.m21 = 0;
	pResult.m22 = 1;
}

/**************************************************************************/
/*!
	This matrix creates a rotation matrix from "angle" whose value 
	is in radian. Save the resultant matrix in pResult.
	*/
/**************************************************************************/
void Mtx33RotRad(Matrix3x3 &pResult, float angle)
{
	// Row 1
	pResult.m00 = std::cos(angle);
	pResult.m01 = -std::sin(angle);
	pResult.m02 = 0;
	// Row 2
	pResult.m10 = std::sin(angle);
	pResult.m11 = std::cos(angle);
	pResult.m12 = 0;
	// Row 3
	pResult.m20 = 0;
	pResult.m21 = 0;
	pResult.m22 = 1;
}

/**************************************************************************/
/*!
	This matrix creates a rotation matrix from "angle" whose value 
	is in degree. Save the resultant matrix in pResult.
	*/
/**************************************************************************/
void Mtx33RotDeg(Matrix3x3 &pResult, float angle)
{
	// Row 1
	pResult.m00 =  std::cos(PIOVER180 * angle);
	pResult.m01 = -std::sin(PIOVER180 * angle);
	pResult.m02 = 0;
	// Row 2
	pResult.m10 = std::sin(PIOVER180 * angle);
	pResult.m11 = std::cos(PIOVER180 * angle);
	pResult.m12 = 0;
	// Row 3
	pResult.m20 = 0;
	pResult.m21 = 0;
	pResult.m22 = 1;
}

/**************************************************************************/
/*!
	This functions calculated the transpose matrix of pMtx 
	and saves it in pResult
	*/
/**************************************************************************/
void Mtx33Transpose(Matrix3x3 &pResult, const Matrix3x3 &pMtx)
{
	// Row 1
	pResult.m00 = pMtx.m00;
	pResult.m01 = pMtx.m10;
	pResult.m02 = pMtx.m20;
	// Row 2
	pResult.m10 = pMtx.m01;
	pResult.m11 = pMtx.m11;
	pResult.m12 = pMtx.m21;
	// Row 3
	pResult.m20 = pMtx.m02;
	pResult.m21 = pMtx.m12;
	pResult.m22 = pMtx.m22;
}
